|
|
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||
Tutorial 2: Programming Beyond Visual Basic
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| Source | |
Sometime you might want to write an application that has an "always-on-top" feature, which ensures that your application's window is not covered by another active application's window. This feature is typical among utilities, such as clocks, that need to be visible at all times, whether or not they are running in the background.
Visual Basic passes arguments to a function ByRef (by reference) by default, which means that VB passes the address of the location in a computer's memory where the argument lives. When you move into API programming, however, passing memory locations to an external procedure can cause a problem. Therefore, most of the time you pass only the value of the argument to a function, not the address of the memory location. For this reason, we use the keyword ByVal (by value) in the code below.
To make your application always-on-top, you use the Windows API function SetWindowPos. The definition for SetWindowPos, which is put in the General Declarations section of a module, is as follows:
Public Declare Function SetWindowPos Lib "user32" _ (ByVal hWnd As Long, _ ByVal hWndInsertAfter As Long, _ ByVal X As Long, _ ByVal Y As Long, _ ByVal cx As Long, _ ByVal cy As Long,_ ByVal wFlags As Long) As Long
The arguments for this function are as follows:
hWnd is the handle of the window to place.
hWndInsertAfter is the preceding window or (as in cases of always on top) the Windows constant that sets the window as topmost. These constants can be retrieved from the API Viewer.
X is the new left position of the window.
Y is the new top position of the window.
cx is the new width of the window measured in pixels.
cy is the new height of the window measured in pixels.
wFlags is the numeric "flag" that tells Windows to consider certain things about window sizing and placement.
These constants can be retrieved from the API Viewer. For a full description of the constants and other associated values for SetWindowPos, see the documentation that comes with your copy of VB.
Whenever you start a program, Windows makes all the windows the program needs on invocation. On creation every window is assigned a number, which is called the window handle and is referred to as an hWnd. Some windows contain other windows. Most of the intrinsic controls are considered windows and therefore have their own window handles. Windows assigns the value of a control's hWnd to the control's HWnd property.
The method of making a window on top with SetWindowPos is straightforward. First, you only have to use SetWindowPos once a session. When you call the function, Windows will juggle or adjust the bits in memory in order to tell the window in question whether it should be on top all the time. After you set the always-on-top bit, you do not have to do anything else, unless you would like to reset the window so it is not always on top.
In order to set the always-on-top bit, use the constant HWND_TOPMOST for the argument hWndInsertAfter. When you pass this value, Windows automatically knows how to set the window to be on top all the time. You need to combine the constants SWP_NOMOVE and SWP_NOSIZE and pass them as the wFlags argument in order to avoid resizing or repositioning issues. Combining the values effectively tells Windows to keep the size and position that are determined by the user.
To use this API function for your coding needs, you must use the API Viewer to retrieve the function's description as well as the values for the constants associated with the function. Figure 6 shows the retrieved functions and constants included in the Selected Items list.
Listing 2 shows an abridged version of the user-defined function SetWinPos() from the module of the prjAPIStuff.vbp project. SetWinPos() is a wrapper function for the SetWindowPos API function.
01 Public Function SetWinPos
(iPos As Integer, lHWnd As Long) As Boolean 02 Dim lWinPos As Long 'A variable to hold
the value of 03 'the API window position constant 04 Dim l As Long 05 06 'Use a SELECT CASE to set the value of the 07 'API Window constant 08 09 Select Case iPos 10 'The window is set to its regular position 11 Case 0 12 lWinPos = HWND_NOTOPMOST 13 'Set the window always on top 14 Case 1 15 lWinPos = HWND_TOPMOST 16 'You have a bad value; leave the function 17 Case Else 18 Exit Function 19 End Select 20 21 'Run the API SetWindowPos function 22 If SetWindowPos(lHWnd, lWinPos,
0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE) Then 23 'If the function is greater than 0 (FALSE), the operation 24 'was successful. Return a True to indicate such. 25 SetWinPos = True 26 End If 27 End Function
The user-defined SetWinPos function takes two arguments: iPos, an integer that determines whether the function will set a window always on top or not, and lHWnd, the handle of the window to process. Lines 9-19 are Select Case statement sthat determine which value to pass to the hWndInsertAfter parameter of the SetWindowPos API function. If iPos is 0, the window to be processed isn't always on top (HWND_NOTOPMOST); if iPos is 1, the window is always on top (HWND_TOPMOST). Any value greater than 1 is considered an error, and the function is terminated, therefore returning the default value of False.
Line 22 is the core of the user-defined function-this is where the API function is called. SetWindowPos takes the value of its HWnd (window handle) argument from lHwnd, the value passed into the user-defined function SetWinPos (line 1). lWinPos is determined within the Select Case statement in lines 9-19. The size and position arguments x, y, cx, and cy are all set to 0 because the window being affected retains its original values. The combined values of the constants SWP_NOMOVE and SWP_NOSIZE are passed to the wFlags argument, effectively telling Windows to not change any of the original size and position settings of the window. If the API function is successful, a True value is passed out of SetWinPos (line 25). A fully commented version of this code is available through the source text.
The way end users should check the Keep on Top check box to select whether they want the window in project prjAPIStuff to always be on top at runtime. When the user checks the check box, the Click() event procedure for the control is called, which in turn calls the user-defined wrapper function SetWinPos. Listing 3 shows the code for the event procedure.
01 Private Sub chkOnTop_Click() 02 Dim b As Boolean 03 If chkOnTop.Value = 1 Then 04 b = SetWinPos(1, Me.hWnd) 05 Me.Caption = "Always on Top" 06 Else
07 b = SetWinPos(0, Me.hWnd) 08 Me.Caption = "Not Always on Top" 09 End If 10 11 'If b returns false, the API function was unsuccessful 12 If Not b Then 13 MsgBox "Positioning Error", vbCritical, "Program Error" 14 End If 15 End Sub
If the value of the check box is set to 1 (checked), the wrapper function sends the API function instructions to set the window (as determined by the argument Me.hWnd) to always on top (line 4). Me is a Visual Basic keyword that refers to the current form or class object in which the word is used.
Also, end users receive a notification in the form's title bar that the window is set to always on top (line 5). If the value of the check box is not checked, the window is set to not always on top (line 7) and an associated notification is sent to the end user (line 8).
|
|
||
|
||||||
|
|||
|
|||
|
| |
| |
| |
|
| |
| |
|
© Copyright 2000 InformIT. All rights reserved. |